﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Opo.Perspective.Core
{
    /// <summary>
    /// Represents a query object that is used to search <see cref="IPerspectiveEntity">IPerspectiveEntities</see>.
    /// </summary>
    public class PerspectiveQuery : IPerspectiveQuery
    {
        private TagCollection _tags = new TagCollection();
        private IList<string> _searchTerms = new List<string>();

        /// <summary>
        /// Gets or sets the tags.
        /// </summary>
        /// <value>The tags.</value>
        public TagCollection Tags
        {
            get
            {
                return _tags;
            }
            set
            {
                _tags = value;
            }
        }
        /// <summary>
        /// Gets or sets the search terms.
        /// </summary>
        /// <value>The search terms.</value>
        public IList<string> SearchTerms
        {
            get
            {
                return _searchTerms;
            }
            set
            {
                _searchTerms = value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PerspectiveQuery"/> class.
        /// </summary>
        public PerspectiveQuery() { }
        /// <summary>
        /// Initializes a new instance of the <see cref="PerspectiveQuery"/> class.
        /// </summary>
        /// <param name="tags">The tags.</param>
        public PerspectiveQuery(TagCollection tags)
            : this(tags, new List<string>()) { }
        /// <summary>
        /// Initializes a new instance of the <see cref="PerspectiveQuery"/> class.
        /// </summary>
        /// <param name="tags">The tags.</param>
        /// <param name="searchTerms">The search terms.</param>
        public PerspectiveQuery(TagCollection tags, IList<string> searchTerms)
        {
            Tags = tags;
            SearchTerms = searchTerms;
        }
        /// <summary>
        /// Parses the specified query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns>A new instance of PerspectiveQurey</returns>
        public static PerspectiveQuery Parse(string query)
        {
            PerspectiveQuery perspectiveQuery = new PerspectiveQuery();

            // get tags
            Regex r = new Regex(@"tag:(?<Tag>\w+)");
            MatchCollection matches = r.Matches(query);
            foreach (Match match in matches)
            {
                string tagName = match.Groups["Tag"].Value;
                if (!String.IsNullOrEmpty(tagName))
                {
                    perspectiveQuery.Tags.Add(tagName);
                }
            }
            query = r.Replace(query, "").Trim();

            // get search terms
            foreach (string searchTerm in query.Split(' '))
            {
                if (!String.IsNullOrEmpty(searchTerm.Trim()))
                {
                    perspectiveQuery.SearchTerms.Add(searchTerm);
                }
            }

            return perspectiveQuery;
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </returns>
        public override string ToString()
        {
            string query = String.Join(" ", Tags.Select(t => "tag:" + t.TagName).ToArray());
            query += " " + String.Join(" ", SearchTerms.ToArray());
            return query;
        }
    }
}
